/**
 * @namespace
 * @desc SC 은행 Common 라이브러리의 최상위 네임스페이스
 */
ScLibs = { };

/**
 * @namespace
 * @desc SC 은행 Common 라이브러리의 UI 네임스페이스
 */
ScLibs.ui = { };

/**
 * @static
 * @method
 * @memberof ScLibs
 * @desc 클래스를 상속한다.
 * @param {Class} sp 슈퍼클래스
 * @param {object} proto 생성할 자식 클래스의 prototype
 * @return {Class} sb 자식 클래스
 * @exmaple
 * var Parents = ScLibs.extend(ScLibs.Observer, { });
 * var Child = Parents.extend({ });
 */
ScLibs.extend = function(sp, proto){
    var sb = function(){
        var args = $.makeArray(arguments);
        this.initialize.apply(this, args);
	};
	
	var F = function(){ },
	        spp = sp.prototype;
	
	F.prototype = spp;
	if(!spp.initialize){
	        spp.initialize = $.noop;
	}
	sb.prototype = new F();
	sb.prototype.constructor = sb;
	sb.base = spp;
	
	if (proto){
	        $.extend(sb.prototype, proto);
	}
	
	sb.extend = function(proto){
	        var sp = this;
	        return ScLibs.extend(sp, proto);
	};
	
	return sb;
};


/**
 * @static
 * @class
 * @memberof ScLibs
 * @desc 커스텀 이벤트를 생성하고 발생 시키는 클래스이다.
 * @example
 *	var observer = new X.util.Observer({
 *		success: function(){ },
 *		error: function(){ }
 *	});
 */
ScLibs.Observer = ScLibs.extend($.noop, {
	initialize: function(listener){
		this.eventTypes = this.eventTypes || {};
		for (var attr in listener) {
			this.eventTypes[attr] = listener[attr];
		}
	},
	/**
	 * @desc custom 이벤트를 등록한다.
	 * @memberof ScLibs.Observer.prototype
	 * @method addEvent
	 * @alias Observer#on
	 * @param {args} ... 
	 * @example 
	 * var observer = new ScLibs.Observer();
	 * observer.addEvent({
	 *	success: function(){ }
	 *  error: function(){ }
	 * });
	 * 
	 * observer.addEvent({
	 *  success: {
	 *      scope: window,
	 *      params: [ ].
	 *      fn: function(){ }
	 *  },
	 *  error: {
	 *      scope: window,
	 *      params: [ ].
	 *      fn: function(){ }
	 *  }
	 * });
	 * observer.addEvent("success", function(){ });
	 */
	addEvent: function(){
		var a = arguments,
			i = a.length,
			eventTypes = this.eventTypes;

		if($.type(a[0]) === 'string'){
			if(eventTypes[a[0]]){
				if($.type(eventTypes[a[0]]) === 'array'){
					this.eventTypes[a[0]].push(a[1]);
				}
				else{
					this.eventTypes[a[0]] = [eventTypes[a[0]], a[1]];
				}
			}
			else{
				this.eventTypes[a[0]] = a[1];
			}

			return;
		}
		while(i--) {
			for (var attr in a[i]){
				if(eventTypes[attr]){
					if($.type(eventTypes[attr]) === 'array'){
						this.eventTypes[attr].push(a[i][attr]);
					}
					else{
						this.eventTypes[attr] = [eventTypes[attr], a[i][attr]];
					}
				}
				else{
					this.eventTypes[attr] = a[i][attr];
				}
			}
		}
	},
	/**
	 * @desc custom 이벤트를 발생시킨다.
	 * @memberof ScLibs.Observer.prototype
	 * @method fireEvent
	 * @alias Observer#fire
	 * @param {Object} 이벤트 핸들러의 scope
	 * @param {String} type 커스텀 이벤트의 이름 
	 * @param {args} args 이벤트 핸들러에 전달될 argument.
	 * @return {Object} 이벤트 핸들러가 return 한 무언가를 반환함.
	 */
	fireEvent: function(o, type, args){
		var params = o.config ? o.config.params || [] : [],
			eventTypes = this.eventTypes;

		if (eventTypes[type]) {
			args = args || [];
			if($.type(eventTypes[type]) === 'object'){
				var event = eventTypes[type];
					params = event.params ? params.concat(event.params) : params;

				return event.fn.apply(event.scope || o, args.concat(params));
			}
			else if($.type(eventTypes[type]) === 'array'){
				for(var i=0, len = eventTypes[type].length; i<len; i++){
					var event = eventTypes[type][i],
						result = false;

					result = event.apply(o.config ? o.config.scope || o : o, args.concat(params));
				}
				return result;
			}
			else{
				return eventTypes[type].apply(o.config ? o.config.scope || o : o, args.concat(params));
			}
		}
	},
	/**
	 * @desc custom 이벤트를 삭제한다
	 * @memberof ScLibs.Observer.prototype
	 * @method removeEvent
	 * @alias Observer#off
	 * @param {String} type
	 */
	removeEvent: function(type){
		if (this.eventTypes[type]) {
			delete this.eventTypes[type];
		}
	},
	/**
	 * @desc 등록한 custom 이벤트를 모두 삭제한다
	 * @memberof ScLibs.Observer.prototype
	 * @method clear
	 */
	clear: function(){
		this.eventTypes = { };
	}
});


ScLibs.Observer.prototype.on = ScLibs.Observer.prototype.addEvent;
ScLibs.Observer.prototype.off = ScLibs.Observer.prototype.removeEvent;
ScLibs.Observer.prototype.fire = ScLibs.Observer.prototype.fireEvent;

